Skip to content

fix(progress-spinner)!: errors following a full review of the component (#DS-5482) - #1979

Merged
artembelik merged 7 commits into
mainfrom
fix/progress-spinner-signals
Sep 8, 2026
Merged

fix(progress-spinner)!: errors following a full review of the component (#DS-5482)#1979
artembelik merged 7 commits into
mainfrom
fix/progress-spinner-signals

Conversation

@artembelik

Copy link
Copy Markdown
Contributor

What

A full review of progress-spinner, in the same shape as the 20.3.0 component reviews.

size was the last accessor input — and it did two things

set size(value: ProgressSpinnerSize | string) {
    this._size = value;
    this.svgCircleRadius = value === 'big' ? '47%' : '42.5%';
}

That side effect is exactly why the automated signal migration skipped it. The radius is a computed now, size is a plain input(), and it is typed ProgressSpinnerSize instead of an arbitrary string — resolving the //@TODO use Exclude<KbqDefaultSizes, 'normal'> that predates this review.

value gained numberAttribute

value="40" used to pass the string "40"; Math.min(100, '40') coerced it by accident. It is a number now.

Closed internals

percentage, dashOffsetPercent and svgCircleRadius are protected. The first two are derived from the value the consumer already binds; the last is SVG geometry, not a contract.

_IdGenerator

The generated id comes from the CDK _IdGenerator instead of a module-level let id = 0, so it no longer collides across lazily loaded bundles. The kbq-progress-spinner-<n> shape is unchanged.

One line outside the component

KbqLoaderOverlay.spinnerSize reports ProgressSpinnerSize rather than string, to keep feeding the narrowed input. It is a narrowing of a getter's return type, so nothing that reads it breaks.

Migration

progress-spinner-signals runs from ng update @koobiq/components@20. It rewrites size reads to calls — on receivers typed KbqProgressSpinner and through template reference variables on <kbq-progress-spinner>, in external and inline templates — and reports the rest.

Documented in docs/guides/migration.{en,ru}.md, section 18.

Testing

  • progress-spinner.component.spec.ts rewritten: 8 → 10 tests. The old ones read percentage off the instance; they assert the rendered stroke-dashoffset, circle radius and host classes now, which is what the value actually drives.
  • progress-spinner-signals/index.spec.ts: 13 tests — auto-fix, idempotence, receiver scoping, template refs, warnings, and the --fix=false path.
  • Full packages/components (4994 tests) and packages/schematics (447 tests) suites pass.
  • check-api is in sync.

No e2e screenshots were regenerated: the e2e cases pass size="compact" / size="big" as before, and the rendered geometry is unchanged.

BREAKING CHANGE

🤖 Generated with Claude Code

`size` was the last accessor input on the spinner, and the reason the automated
signal migration skipped it: its setter stored the size and computed the SVG
circle radius in one go. The radius is a `computed` now and `size` is a plain
`input()`, typed `ProgressSpinnerSize` instead of an arbitrary string — which
resolves a TODO that predates this review.

`value` gained `numberAttribute`: `value="40"` used to pass the string `"40"`,
which the percentage arithmetic coerced by accident.

`percentage`, `dashOffsetPercent` and `svgCircleRadius` are `protected`. They are
derived from the inputs the consumer already binds, and the last one is SVG
geometry rather than a contract.

The generated `id` comes from the CDK `_IdGenerator` instead of a module-level
counter, so it no longer collides across lazily loaded bundles.

`KbqLoaderOverlay.spinnerSize` reports `ProgressSpinnerSize` rather than `string`
to keep feeding the narrowed input.

BREAKING CHANGE: `KbqProgressSpinner.size` is a signal and no longer accepts an
arbitrary string; `percentage`, `dashOffsetPercent` and `svgCircleRadius` are
protected; `value` is a `numberAttribute` input, so a `null` binding yields `NaN`
where it used to clamp to `0`. Reported and partly rewritten by the
`progress-spinner-signals` schematic.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions github-actions Bot added bug Something isn't working breaking changes labels Sep 2, 2026
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Visit the preview URL for this PR (updated for commit aeafe75):

https://koobiq-next--prs-1979-k1vbiog4.web.app

(expires Fri, 11 Sep 2026 12:45:47 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: c9e37e518febda70d0317d07e8ceb35ac43c534c

@lskramarov lskramarov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review — max effort

15 findings, ranked most severe first. Thirteen are correctness, one is test coverage, one is the
migration guide.

The two that block: the schematic never writes anything under ng update
(index.ts:394), and numberAttribute without a fallback makes a nullish [value] paint a full ring
instead of an empty one (progress-spinner.component.ts:64).

Most of the rest are guards that exist in the newer sibling migrations (navbar-signals-and-aria,
button-toggle-signals-and-aria) but not in this clone of the older alert-signals: the assignment
lookahead in the ref regex, variableScope for block-scoped locals, initializerTypeOf for
inject()/viewChild() receivers, and the template-side manual-member report.

Posted by Claude Code.

Comment thread packages/schematics/src/migrations/progress-spinner-signals/index.ts Outdated
Comment thread packages/components/progress-spinner/progress-spinner.component.ts Outdated
Comment thread packages/schematics/src/migrations/progress-spinner-signals/index.ts Outdated
Comment thread packages/schematics/src/migrations/progress-spinner-signals/index.ts Outdated
Comment thread packages/schematics/src/migrations/progress-spinner-signals/index.ts Outdated
Comment thread packages/schematics/src/migrations/progress-spinner-signals/index.ts Outdated
Comment thread packages/schematics/src/migrations/progress-spinner-signals/data.ts Outdated
Comment thread packages/components/progress-spinner/progress-spinner.component.ts
Comment thread packages/components/progress-spinner/progress-spinner.component.spec.ts Outdated
Comment thread docs/guides/migration.en.md Outdated
artembelik and others added 3 commits September 3, 2026 15:41
`numberAttribute` with no fallback turned a null binding into `NaN`, and the
value feeds a `stroke-dashoffset` percentage — `NaN%` is not a CSS length, so
the browser dropped the declaration and the circle rendered full. It falls back
to 0, which is what the pre-migration input did.

The schematic counted a `.html` file as a consumer only when it had a `size` read
to rewrite, so a template-only consumer never heard that `size` no longer accepts
an arbitrary string.

Tests: the uniqueness assertion compared a generated id against a bound one, so
it passed without testing uniqueness; and nothing covered `value="40"` as a
static attribute, which is the case the transform exists for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The autocomplete (#1985) and badge (#1978) reviews landed on main in the meantime,
so their entries and subsections came with it:

- migrations.json / collection.json: kept main's entries and appended
  progress-spinner-signals.
- migration.en.md / migration.ru.md: main's block here runs Autocomplete, Badge,
  Notification center, Popover, all of which sort before Progress spinner, so this
  subsection goes after them rather than before.

`check-public-api-any` counted progress-spinner 0 -> 1 on the merged tree. The
`unknown` was the hand-written `value` transform, not an Angular signature, so it
is narrowed to `number | string | null | undefined` instead of recorded: that keeps
`[value]="progress$ | async"` and `value="40"` type-checking while an object or an
array stays a template type error, which is the static check the review said this
PR had dropped.
@artembelik artembelik self-assigned this Sep 8, 2026
@artembelik
artembelik marked this pull request as ready for review September 8, 2026 08:12
Copilot AI lite review requested due to automatic review settings September 8, 2026 08:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It introduces a breaking API refactor plus a large new schematic-based migration, which warrants final human review despite the added tests and docs.

Pull request overview

This PR completes a full review of progress-spinner by finalizing its signal-based API, tightening its public types, and providing an ng update migration to rewrite consumer reads and report manual work. It also updates documentation and a dependent component (loader-overlay) to align with the narrowed spinner size input.

Changes:

  • Refactors KbqProgressSpinner to a fully signal-based surface: size becomes an input(), value gains a typed numberAttribute transform, and derived internals become protected signals.
  • Switches generated IDs to CDK _IdGenerator to avoid cross-bundle collisions.
  • Adds the progress-spinner-signals migration (schema, implementation, tests) and documents it in the v20 migration guides.
File summaries
File Description
tools/public_api_guard/components/progress-spinner.api.md Updates the extracted public API snapshot for the new signal-based members and narrowed ProgressSpinnerSize.
tools/public_api_guard/components/loader-overlay.api.md Updates API snapshot to reflect spinnerSize now returning ProgressSpinnerSize.
packages/schematics/src/migrations/progress-spinner-signals/schema.ts Adds TS schema interface for the new migration options.
packages/schematics/src/migrations/progress-spinner-signals/schema.json Adds JSON schema for the migration (project, fix).
packages/schematics/src/migrations/progress-spinner-signals/README.md Documents what the migration rewrites, reports, and how to run it.
packages/schematics/src/migrations/progress-spinner-signals/index.ts Implements the migration: TS receiver detection + template ref rewriting + warnings/summary output.
packages/schematics/src/migrations/progress-spinner-signals/index.spec.ts Adds a dedicated test suite covering rewrites, warnings, idempotence, and --fix=false.
packages/schematics/src/migrations/progress-spinner-signals/data.ts Defines migration constants, warning patterns, and summary text.
packages/schematics/src/migrations.json Registers progress-spinner-signals for 20.3.0-0.
packages/schematics/src/collection.json Exposes the migration as a schematic with its schema.
packages/components/progress-spinner/progress-spinner.component.ts Refactors spinner inputs to signals, adds typed coercion for value, makes derived values protected, and adopts _IdGenerator.
packages/components/progress-spinner/progress-spinner.component.spec.ts Reworks unit tests to assert rendered output (dashoffset/radius/classes) and new coercion/id behavior.
packages/components/progress-spinner/progress-spinner.component.html Updates template reads to call computed signals (svgCircleRadius(), dashOffsetPercent()).
packages/components/loader-overlay/loader-overlay.component.ts Narrows spinnerSize to ProgressSpinnerSize to match the spinner’s tightened input type.
docs/guides/migration.ru.md Documents the progress-spinner migration and the behavior/type changes (RU).
docs/guides/migration.en.md Documents the progress-spinner migration and the behavior/type changes (EN).
Review details
  • Files reviewed: 16/16 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

artembelik and others added 2 commits September 8, 2026 11:17
20.3.0 was released on main, so #2005 moved every staged migration to 21.0.0-0.
Two things the merge needed beyond the automatic resolution:

- progress-spinner-signals merged in still registered for 20.3.0-0, which git had
  no reason to touch because the entry is an addition. At that version the
  migration would never run for anyone upgrading to 21, so it joins the other 28
  on 21.0.0-0, together with the version in its README and its data.ts docblock.
- loader-overlay.api.md conflicted: this branch narrowed `spinnerSize` to
  `ProgressSpinnerSize` while main added the `surface` input. The file is
  generated, so it was regenerated with `approve-api` rather than merged by hand;
  the result carries both.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comment thread packages/components/loader-overlay/loader-overlay.component.ts
The markdown review (#1981) landed on main, so only its two registry entries
conflicted, at the append point every review branch shares: kept main's entries
and appended progress-spinner-signals after them.

Both guides auto-merged correctly this time - main's block already ends with
Popover and the Markdown subsection it added sorts before Progress spinner, so
the alphabetical order came out right without help. The migration is already
registered for 21.0.0-0 from the previous merge, so nothing to re-version.
@artembelik
artembelik merged commit a8a6be7 into main Sep 8, 2026
14 checks passed
@artembelik
artembelik deleted the fix/progress-spinner-signals branch September 8, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking changes bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants